// Copyright (c) 2007, Brian Duff

// See LICENSE for full license details.


package org.dubh.jdant;

import java.io.File;

import java.io.IOException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Parses an external library (*.library) file.
 *
 * @author brian.duff@dubh.org
 */
final class ExternalLibraryParser
{
  private final File libraryFile;
  private Collection<String> exportedIds = null;
  
  ExternalLibraryParser( File libraryFile )
  {
    this.libraryFile = libraryFile;
  }
  
  void setExportedIds( Collection<String> exportedIds )
  {
    this.exportedIds = exportedIds;
  }
  
  private boolean isExported( String id )
  {
    if ( exportedIds == null ) return false;
    return exportedIds.contains( id );
  }
  
  Library library( File projectFile ) throws IOException
  {
    try
    {
      LibraryHandler handler = new LibraryHandler();
      Util.newSAXParser().parse( libraryFile, handler );
      
      // The id of an external library is the relative path from the project
      // file to the library file.
      File normalizedPath = Util.normalize( libraryFile );
      String libRelative = Util.toRelativePath( projectFile, normalizedPath );
      
      return new Library.Builder( libRelative, handler.classpath() )
        .exported( isExported( libRelative ) ) 
        .type( LibraryType.FILE )
        .build();
    }
    catch ( SAXException e )
    {
      // Ugliness for 1.5 compatibility.
      IOException ioe = new IOException( "Failed to process library " + libraryFile );
      ioe.initCause( e );
      throw ioe;
    }
  }
  

  private class LibraryHandler extends DefaultHandler
  {
    private final List<File> _classpath = new ArrayList<File>();
    private boolean inClasspath = false;
    
    List<File> classpath()
    {
      return _classpath;
    }
    
    @Override
    public void startElement(String uri, String localName, String qName,
                             Attributes attributes)
    {
      if ( isClassPath( localName ) ) startClassPath();
      if ( isItem( localName ) ) startItem( attributes );
    }

    @Override
    public void endElement(String uri, String localName, String qName)
      throws SAXException
    {
      if ( isClassPath( localName ) ) endClassPath();
    }
    
    private void startItem( Attributes attributes )
    {
      if ( inClasspath )
      {
        String path = attributes.getValue( "path" );
        String fullPath = libraryFile.getParentFile().getPath() + 
          File.separatorChar + path;
        _classpath.add( Util.normalize( new File( fullPath ) ) );
      }
    }
    
    private void startClassPath()
    {
      inClasspath = true;
    }
    
    private void endClassPath()
    {
      inClasspath = false;
    }
    
    private boolean isItem( String local )
    {
      return "Item".equals( local );
    }
    
    private boolean isClassPath( String local )
    {
      return "classPath".equals( local );
    }
  }
  
}
